﻿#include "EditorPageAreaViewModel.h"

#include "Framework/Editor.h"

#include "Pages/EditorPageModel.h"
#include "Pages/EditorPageViewModel.h"

#include "PageArea/EditorPageAreaManagerModel.h"

#include "Object/NewObject.h"

#include "Asset/EditorDefaultPackage.h"

#include "Event/KeyboardEvent.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"

#include "Window/EditorWindowGroupModel.h"
#include "Window/EditorSubwindowModel.h"

#include "Pages/TextFile/EditorTextFilePageViewModel.h"

#include "Containers/Format.h"

void REditorPageAreaViewModel::BindModel(TSharedObjectPtr<REditorPageAreaModel> InModel)
{
    Model = InModel;

    CloseIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconClose");
    CloseIconHighlighted= REditorDefaultPackage::Get()->GetIcon(U"CodiconClose_Highlight");
    UnsavedIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconCircleFilled");
    UnsavedIconHighlighted= REditorDefaultPackage::Get()->GetIcon(U"CodiconCircleFilled_Highlight");
    HorizontalSpliterIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconSplitHorizontal");
    VerticalSpliterIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconSplitVertical");

    auto CreatePageViewModel = [&](TSharedObjectPtr<REditorPageModel> PageModel)
    {
        auto ViewModelClass = REditor::Get()->GetViewModelClass(PageModel->GetClass());
        auto ViewModel = NewObject<REditorPageViewModel>(ViewModelClass,this);
        ViewModel->BindModel(PageModel);
        Pages.Add(ViewModel);
    };

    for(int64_t PageIndex=0;PageIndex<Model->GetPageNum();PageIndex++)
    {
        auto PageModel = Model->GetPage(PageIndex);
        CreatePageViewModel(PageModel);
    }
    Model->OnPageAdded.Bind([this,CreatePageViewModel](TSharedObjectPtr<REditorPageModel> PageModel)
    {
        CreatePageViewModel(PageModel);
        OnPageAdded.ExecuteIfBound(Pages.Last());
    });
    Model->OnPageClosed.Bind([this](int64_t Index)
    {
        Pages.RemoveAt(Index);
        OnPageClosed.ExecuteIfBound(Index);
    });
    Model->OnPageReplaced.Bind([this](int64_t Index)
    {
        auto ViewModelClass = REditor::Get()->GetViewModelClass(Model->GetPage(Index)->GetClass());
        Pages[Index] = NewObject<REditorPageViewModel>(ViewModelClass,this);
        Pages[Index]->BindModel(Model->GetPage(Index));
        OnPageReplaced.ExecuteIfBound(Index);
    });

    // for(int64_t SubAreaIndex=0;SubAreaIndex<Model->GetSubAreaNum();SubAreaIndex++)
    // {
    //     auto SubAreaModel = Model->GetSubArea(SubAreaIndex);
    //     auto SubAreaViewModel = NewObject<REditorPageAreaViewModel>(this);
    //     SubAreaViewModel->BindModel(SubAreaModel);
    //     SubAreaViewModels.Add(SubAreaViewModel);
    // }

    // Model->OnLayoutChanged.Bind([this]()
    // {
    //     //页面和页面区域存在循环引用。
    //     //页面的Tick函数与循环引用存在冲突，即便使用GC也无法解决
    //     //这里直接销毁
    //     for(auto& Page:Pages)
    //     {
    //         WH::DestroyObject(Page.Get());
    //     }
    //     Pages.Clear();

    //     for(auto& SubArea:SubAreaViewModels)
    //     {
    //         WH::DestroyObject(SubArea.Get());
    //     }
    //     SubAreaViewModels.Clear();

    //     for(int64_t SubAreaIndex=0;SubAreaIndex<Model->GetSubAreaNum();SubAreaIndex++)
    //     {
    //         auto SubAreaModel = Model->GetSubArea(SubAreaIndex);
    //         auto SubAreaViewModel = NewObject<REditorPageAreaViewModel>(this);
    //         SubAreaViewModel->BindModel(SubAreaModel);
    //         SubAreaViewModels.Add(SubAreaViewModel);
    //     }

    //     for(int64_t PageIndex=0;PageIndex<Model->GetPageNum();PageIndex++)
    //     {
    //         auto PageModel = Model->GetPage(PageIndex);
    //         auto ViewModelClass = REditor::Get()->GetViewModelClass(PageModel->GetClass());
    //         auto ViewModel = NewObject<REditorPageViewModel>(ViewModelClass,this);
    //         ViewModel->BindModel(PageModel);
    //         Pages.Add(ViewModel);
    //     }

    //     OnLayoutChanged.ExecuteIfBound();
    // });

    //搜索替换相关
    CollapsedIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronRight");
    ExpandedIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconChevronDown");

    FindPreviousIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconArrowUp");
    FindPreviousDarkIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconArrowUp_Dark");
    FindNextIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconArrowDown");
    FindNextDarkIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconArrowDown_Dark");
    FindInSelectionIcon = REditorDefaultPackage::Get()->GetIcon(U"CodiconListSelection");
    CloseFindAndReplaceIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconClose");
    ReplaceIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconReplace");
    ReplaceAllIcon= REditorDefaultPackage::Get()->GetIcon(U"CodiconReplaceAll");
}

int64_t REditorPageAreaViewModel::GetPageNum() const
{
    return Pages.Num();
}

TSharedObjectPtr<REditorPageViewModel> REditorPageAreaViewModel::GetPage(int64_t Index) const
{
    return Pages[Index];
}

bool REditorPageAreaViewModel::IsShowingPageContent(int64_t Index) const
{
    return Model->GetFrontPageIndex()==Index;
}

void REditorPageAreaViewModel::SelectPage(int64_t Index)
{
    //清除当前页面的搜索结果
    {
        auto OldPage=GetPage(Model->GetFrontPageIndex());
        if(OldPage->IsA<REditorTextFilePageViewModel>())
        {
            REditorTextFilePageViewModelPtr TextFilePage=OldPage;
            TextFilePage->ClearSearch();
        }
    }
    


    Model->BringPageFront(Index);
    Model->GetManager()->FocusPageArea(Model);
    REditorWindowGroupModel::Get()->FocusePageAreaManager(Model->GetManager());
}

bool REditorPageAreaViewModel::IsHighlighted(int64_t Index) const
{
    return Model->GetFrontPageIndex()==Index &&
           Model->IsFocusedInTree();
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetPageIcon(int64_t Index) const
{
    return Pages[Index]->GetIcon();
}


CString REditorPageAreaViewModel::GetPageTitle(int64_t Index) const
{
    return Pages[Index]->GetTitle();
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetCloseIcon(
    int64_t Index
    ,bool bIsTitleHovored
    ,bool bIsIconHovored) const
{
    if(IsShowingPageContent(Index))
    {
        if(HasUnsavedData(Index) && !bIsIconHovored)
        {
            return UnsavedIconHighlighted;
        }
        
        return CloseIconHighlighted;
    }
    else
    {
        if(HasUnsavedData(Index) && !bIsIconHovored)
        {
            return UnsavedIcon;
        }

        if(bIsTitleHovored )
        {
            return CloseIcon;
        }
        return nullptr;
    }

}

bool REditorPageAreaViewModel::HasUnsavedData(int64_t Index) const
{
    return Pages[Index]->HasUnsavedData();
}

void REditorPageAreaViewModel::SaveFile(int64_t Index)
{
    Pages[Index]->SaveFile();
}

void REditorPageAreaViewModel::ClosePage(int64_t Index)
{
    Model->GetManager()->ClosePage(Model,Index);
}

TVector<SEditorContextMenuLine> REditorPageAreaViewModel::CreateTitleContext(int64_t Index) const
{
    TVector<SEditorContextMenuLine> Result;
    {
        auto& Close=Result.Emplace();
        Close.Text=U"关闭(未实现)";
        Close.OnClicked=[this]()
        {
            //TODO 关闭本页面
        };
    }

    {
        auto& CloseOthers=Result.Emplace();
        CloseOthers.Text=U"关闭其他(未实现)";
        CloseOthers.OnClicked=[this]()
        {
            //TODO 关闭其他页面
        };

    }
    
    {
        auto& CloseRight=Result.Emplace();
        CloseRight.Text=U"关闭右侧(未实现)";
        CloseRight.OnClicked=[this]()
        {
            //TODO 关闭右侧页面
        };
    }

    {
        auto& CloseSaved=Result.Emplace();
        CloseSaved.Text=U"关闭已保存(未实现)";
        CloseSaved.OnClicked=[this]()
        {
            //TODO 关闭已保存页面
        };
    }

    {
        auto& CloseAll=Result.Emplace();
        CloseAll.Text=U"关闭所有(未实现)";
        CloseAll.OnClicked=[this]()
        {
            //TODO 关闭所有页面
        };
    }

    //分割线
    {
        auto& Line=Result.Emplace();
        Line.bIsSeparator=true;
    }

    {
        auto& CopyPath=Result.Emplace();
        CopyPath.Text=U"复制路径(未实现)";
        CopyPath.OnClicked=[this]()
        {
            //TODO 复制文件绝对路径
        };
    }

    {
        auto& CopyRelativePath=Result.Emplace();
        CopyRelativePath.Text=U"复制相对路径(未实现)";
        CopyRelativePath.OnClicked=[this]()
        {
            //TODO 复制文件路径(相对于项目根目录)
        };
    }

    //分割线
    {
        auto& Line=Result.Emplace();
        Line.bIsSeparator=true;
    }

    {
        auto& Reopen=Result.Emplace();
        Reopen.Text=U"更换编辑器重新打开(未实现)";
        Reopen.OnClicked=[this]()
        {
            //TODO 更换编辑器重新打开
        };
    }

    //分割线
    {
        auto& Line=Result.Emplace();
        Line.bIsSeparator=true;
    }    

    {
        auto& ShowInExplorer=Result.Emplace();
        ShowInExplorer.Text=U"在操作系统文件管理器中显示(未实现)";
        ShowInExplorer.OnClicked=[this]()
        {
            //TODO 在系统的文件管理器中显示
        };
    }

    {
        auto& ShowInSelfExplorer=Result.Emplace();
        ShowInSelfExplorer.Text=U"在内部文件管理器中显示(未实现)";
        ShowInSelfExplorer.OnClicked=[this]()
        {
            //TODO 在编辑器内部的文件管理器中显示
        };
    }

    //分割线
    {
        auto& Line=Result.Emplace();
        Line.bIsSeparator=true;
    }    

    {
        auto& MoveToNewWindow=Result.Emplace();
        MoveToNewWindow.Text=U"移动到新窗口(未实现)";
        MoveToNewWindow.OnClicked=[this]()
        {
            //TODO 移动到新窗口
        };
    }

    {
        auto& CopyToNewWindow=Result.Emplace();
        CopyToNewWindow.Text=U"复制到新窗口";
        CopyToNewWindow.OnClicked=[this,Index]()
        {
            auto NewSubWindow=REditorWindowGroupModel::Get()->CreateSubwindow();
            auto NewPageArea=NewSubWindow->GetPageArea();
            NewPageArea->AddPageInDefaultArea(
                Pages[Index]->GetModel()->ShareClone(nullptr)
                ,true);
            
            // NewPageArea->AddPage(
            //     Pages[Index]->GetModel()->ShareClone(NewPageArea.Get()),true);

        };
    }

    return Result;
}

float REditorPageAreaViewModel::GetTitleOperationBarWidth()
{
    const int64_t FixedOperationBarNum=1;

    if(Model->GetFrontPageIndex()!=-1)
    {
        return FixedOperationBarNum
            *REditor::Get()->CurrentTheme->PageAreaButtonSize
            +Pages[Model->GetFrontPageIndex()]->GetOperationsWidth()
            + TitleOperationBarSpaceing
            ; 
    }

    return FixedOperationBarNum
        *REditor::Get()->CurrentTheme->PageAreaButtonSize
        + TitleOperationBarSpaceing
        ; 
    
}

float REditorPageAreaViewModel::GetPageOperationBarWidth()
{
    if(Model->GetFrontPageIndex()==-1)
    {
        return 0;
    }
    return Pages[Model->GetFrontPageIndex()]->GetOperationsWidth();
}

bool REditorPageAreaViewModel::IsShowingPageOperation(int64_t Index) const
{
    return Model->GetFrontPageIndex()==Index;
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetSplitAreaButtonIcon()
{
    if(SKeyboardEvent::IsAnyAltDown())
    {
        return VerticalSpliterIcon;
    }
    return HorizontalSpliterIcon;
}

void REditorPageAreaViewModel::SplitArea()
{
    if(SKeyboardEvent::IsAnyAltDown())
    {
        Model->GetManager()->SplitToDown(Model);
    }
    else
    {
        Model->GetManager()->SplitToRight(Model);
    }
}

// int64_t REditorPageAreaViewModel::GetSubAreaNum() const
// {
//     return SubAreaViewModels.Num();
// }

// TSharedObjectPtr<REditorPageAreaViewModel> REditorPageAreaViewModel::GetSubArea(int64_t Index) const
// {
//     return SubAreaViewModels[Index];
// }

// float REditorPageAreaViewModel::GetSubAreaSizeWeight(int64_t Index) const
// {
//     return Model->GetSubAreaSizeWeight(Index);
// }

// bool REditorPageAreaViewModel::IsSubAreaVertical() const
// {
//     return Model->IsSubAreaVertical();
// }

bool REditorPageAreaViewModel::IsReplace() const
{
    return Model->IsShowingReplaceWidget();
}

void REditorPageAreaViewModel::ToggleReplace()
{
    Model->ToggleReplaceWidget();
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetToggleReplaceIcon() const
{
    if(Model->IsShowingReplaceWidget())
    {
        return ExpandedIcon;
    }

    return CollapsedIcon;
}

float REditorPageAreaViewModel::GetTextWidth() const
{
    return CurrentTextWidth;
}

void REditorPageAreaViewModel::UpdateSearchText(const CString &InText)
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    TextFilePage->SearchText(InText);
}

float REditorPageAreaViewModel::GetFindResultTextWidth() const
{
    return ShowFindResultText? FindResultTextWidth : 0;
}

CString REditorPageAreaViewModel::GetFindResultText() const
{
    auto PageIndex=Model->GetFrontPageIndex();
    if(PageIndex<0)
    {
        return U"";
    }
    auto CurrentPage=GetPage(Model->GetFrontPageIndex());
    if(!CurrentPage->IsA<REditorTextFilePageViewModel>())
    {
        return U"";
    }

    REditorTextFilePageViewModelPtr TextFilePage=CurrentPage;
    auto Count=TextFilePage->GetSearchResultCount();

    if(Count>0)
    {
        auto SearchIndex=TextFilePage->GetCurrentSearchIndex();
        CString Index=SearchIndex==-1? CString(U"?"):CString(SearchIndex+1);
        return WH::Format(U"第{}项，共{}项",Index,Count);
    }
    return U"未找到";
}

SColor REditorPageAreaViewModel::GetFindResultTextColor() const
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    auto Count=TextFilePage->GetSearchResultCount();

    if(Count>0)
    {
        return SColor::White;
    }
    return SColor::Red;
}

bool REditorPageAreaViewModel::IsFindResultEmpty() const
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    return TextFilePage->GetSearchResultCount()==0;
}

void REditorPageAreaViewModel::GotoPreviousMatched()
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    TextFilePage->GotoPreviousMatched();
}

void REditorPageAreaViewModel::GotoNextMatched()
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    TextFilePage->GotoNextMatched();
}

CString REditorPageAreaViewModel::GetReplaceText() const
{
    return ReplaceText;
}

void REditorPageAreaViewModel::UpdateReplaceText(const CString &InText)
{
    ReplaceText=InText;
}

void REditorPageAreaViewModel::Replace()
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    TextFilePage->Replace(ReplaceText);
}

void REditorPageAreaViewModel::ReplaceAll()
{
    REditorTextFilePageViewModelPtr TextFilePage=GetPage(Model->GetFrontPageIndex());
    TextFilePage->ReplaceAll(ReplaceText);
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetPreviousIcon() const
{
    return FindPreviousIcon;
}

TSharedObjectPtr<RTexture2D> REditorPageAreaViewModel::GetNextIcon() const
{
    return FindNextIcon;
}

bool REditorPageAreaViewModel::IsFindOrReplaceVisible() const
{
    return Model->IsShowingFindAndReplaceDialog()
        && Model->GetFrontPageIndex()!=-1
        && Model->GetPage(Model->GetFrontPageIndex())->SupportFindAndReplaceText();
       
    
}

void REditorPageAreaViewModel::CloseFindAndReplace()
{
    Model->CloseFindAndReplaceDialog();
}
